/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */


import path from 'path';

import { cloneDeep } from '@baize/wdk';
import { HvigorLogger, TrackAPI } from '@ohos/hvigor';

import { buildOptionPath, getHookFilePath } from '../../../common/build-option-path-info.js';
import { CoreProduct } from '../../../common/global/core-product.js';
import { CoreProjectProfile } from '../../../common/global/core-project-profile.js';
import { BuildDirConst } from '../../../const/build-directory-const.js';
import { CommonConst } from '../../../const/common-const.js';
import { ProjectBuildProfile } from '../../../options/build/project-build-profile.js';
import { AppJson } from '../../../options/configure/app-json-options.js';
import { BuildModeManager } from '../../../project/build-option/build-mode-manager.js';
import { ProjectTaskService } from '../../../tasks/service/project-task-service.js';
import { ohPackageLoader } from '../../../utils/loader/file/oh-package-loader';
import { projectBuildProfileLoader } from '../../../utils/loader/file/project-build-profile-loader.js';
import { resModelLoader } from '../../../utils/loader/file/res-model-loader.js';
import { AbstractProjectPlugin } from '../../common/abstract-project-plugin.js';
import { OhosProjectContext, OhpmDependencyInfo, Product } from '../plugin-context.js';

import ProductBuildOpt = ProjectBuildProfile.ProductBuildOpt;

/**
 * Project级别的上下文信息
 */
export class OhosProjectContextImpl implements OhosProjectContext {
  private readonly projectPlugin: AbstractProjectPlugin;
  private currentProduct: Product | undefined;
  private projectPath: string;
  private buildProductOutputPath: string | undefined;
  private buildRootPath: string | undefined;
  private taskService: ProjectTaskService;
  private projectOhPackagePath: string;
  private logger: HvigorLogger = HvigorLogger.getLogger(OhosProjectContextImpl.name);

  constructor(projectPlugin: AbstractProjectPlugin, taskService: ProjectTaskService) {
    this.projectPlugin = projectPlugin;
    this.projectPath = this.projectPlugin.getProjectModel()!.getProject().getNodeDir();
    this.taskService = taskService;
    this.projectOhPackagePath = path.resolve(this.projectPath, CommonConst.OH_PACKAGE_JSON5);

    // 初始化resModelLoader需要用的sdk中的schema的路径
    resModelLoader.initSchemaPath(this.taskService.getSdkInfo().getAppSchema(), this.taskService.getSdkInfo().getModuleSchema());
    this.initCurrentProduct();

    // 必须在initCurrentProduct后面执行
    this.initBuildPath();
  }

  @TrackAPI getOhpmDependencyInfo(): Record<string, OhpmDependencyInfo> {
    return this.taskService.getOhpmDependencyInfo();
  }

  @TrackAPI getOhpmRemoteHspDependencyInfo(isSigned = false): Record<string, OhpmDependencyInfo> {
    return this.taskService.getOhpmRemoteHspDependencies(this.taskService, this.currentProduct?.getProductName(), isSigned);
  }

  @TrackAPI getProjectName(): string {
    return this.projectPlugin._project.getName();
  }

  @TrackAPI getBuildMode(): string {
    return BuildModeManager.getBuildMode();
  }

  @TrackAPI getProjectPath(): string {
    return this.projectPlugin._project.getNodeDir();
  }

  @TrackAPI getCurrentProduct(): Product {
    return this.currentProduct as Product;
  }

  initCurrentProduct() {
    const productBuildOpt: ProductBuildOpt = CoreProjectProfile.getInstance(this.projectPath).getCurrentProductOpt();
    this.currentProduct = new CoreProduct(productBuildOpt, this.taskService.getProjectModel());
  }

  initBuildPath() {
    this.buildRootPath = this.taskService.getPathInfo().getProjectBuildPath();
    this.buildProductOutputPath = path.resolve(this.buildRootPath, BuildDirConst.BUILD_OUTPUTS, this.currentProduct!.getProductName()!);
  }

  @TrackAPI getBuildProductOutputPath(): string {
    return this.buildProductOutputPath!;
  }

  @TrackAPI getBuildRootPath(): string {
    return this.buildRootPath!;
  }

  @TrackAPI getAppJsonOpt(): AppJson.AppOptObj {
    return cloneDeep(resModelLoader.getAppJson(path.resolve(this.projectPath, CommonConst.APP_SCOPE, CommonConst.APP_CONFIG)));
  }

  @TrackAPI getBuildProfileOpt(): ProjectBuildProfile.ProjectProfileOpt {
    return cloneDeep(projectBuildProfileLoader.getBuildProfile());
  }

  @TrackAPI setAppJsonOpt(appJsonOpt: AppJson.AppOptObj): void {
    if (this.taskService.isFaMode()) {
      this.logger.printErrorExit('FA_MODE_NOT_SUPPORT_MODIFY_FILE', ['app.json5']);
    }
    const appJsonPath = path.resolve(this.projectPath, CommonConst.APP_SCOPE, CommonConst.APP_CONFIG);
    resModelLoader.setAppJson(appJsonPath, appJsonOpt);
    buildOptionPath.setAppConfigPath(appJsonPath, appJsonOpt, getHookFilePath());
  }

  @TrackAPI setBuildProfileOpt(buildProfileOpt: ProjectBuildProfile.ProjectProfileOpt): void {
    if (this.taskService.isFaMode()) {
      this.logger.printErrorExit('FA_MODE_NOT_SUPPORT_MODIFY_FILE', ['buildProfile']);
    }
    projectBuildProfileLoader.checkBuildProfile(projectBuildProfileLoader.getBuildProfile(), buildProfileOpt);
    projectBuildProfileLoader.setBuildProfileJson5Obj(this.getProjectName(), buildProfileOpt);

    // 顺序不能变 设置后需要刷新已经合并的数据项
    this.projectPlugin.getProjectModel()?.refreshData();
    this.projectPlugin.initBuildOptionMap(getHookFilePath());
    this.taskService.refreshData();
  }

  @TrackAPI getDependenciesOpt(): any {
    return cloneDeep(ohPackageLoader.getDependenciesOpt(this.projectOhPackagePath));
  }

  @TrackAPI getDevDependenciesOpt(): any {
    return cloneDeep(ohPackageLoader.getDevDependenciesOpt(this.projectOhPackagePath));
  }

  @TrackAPI getDynamicDependenciesOpt(): any {
    return cloneDeep(ohPackageLoader.getDynamicDependenciesOpt(this.projectOhPackagePath));
  }

  @TrackAPI setDependenciesOpt(dependencies: any): void {
    ohPackageLoader.setDependenciesOpt(this.projectOhPackagePath, dependencies);
  }

  @TrackAPI setDevDependenciesOpt(devDependencies: any): void {
    ohPackageLoader.setDevDependenciesOpt(this.projectOhPackagePath, devDependencies);
  }

  @TrackAPI setDynamicDependenciesOpt(dynamicDependencies: any): void {
    ohPackageLoader.setDynamicDependenciesOpt(this.projectOhPackagePath, dynamicDependencies);
  }

  @TrackAPI getOverrides(): any {
    return cloneDeep(ohPackageLoader.getOverrides(this.projectOhPackagePath));
  }

  @TrackAPI setOverrides(overrides: any): void {
    ohPackageLoader.setOverrides(this.projectOhPackagePath, overrides);
  }
}
